package alejandro.castro.abstracts;



import alejandro.castro.asteroid.moving.MovingHorizontal;
import alejandro.castro.asteroid.moving.MovingNoneH;
import alejandro.castro.asteroid.moving.MovingNoneV;
import alejandro.castro.asteroid.moving.MovingState;
import alejandro.castro.asteroid.moving.MovingToBottom;
import alejandro.castro.asteroid.moving.MovingToLeft;
import alejandro.castro.asteroid.moving.MovingToRight;
import alejandro.castro.asteroid.moving.MovingToTop;
import alejandro.castro.asteroid.moving.MovingVertical;

import com.uqbar.vainilla.DeltaState;

public abstract class MovableComponent extends PlaceableComponent {
	
	public final double TOPSPEEDSQUARE = 62500;
	public final double ACCELERATION   = 200;
	public final double MAXANGLE       = Math.PI * 2;
	public final double TURNSPEED      = 1;
	public final double TURNPERCENT    = 500;
	public MovingHorizontal hMovingState;
	public MovingVertical   vMovingState;
	public double currentAngle;
	public double tempHip;
	public double xMove;
	public double yMove;

	public MovableComponent(double x, double y) {
		super(x, y);
		this.currentAngle = 0;
		this.xMove =  Math.cos(currentAngle);
		this.yMove =  -Math.sin(currentAngle);
		this.setNoneEstadoH();
		this.setNoneEstadoV();
	}
	
	@Override
	public void update(DeltaState delta) {			
		super.update(delta);
		this.getMovingStateV().updateV(this, delta);
		this.getMovingStateH().updateH(this, delta);
		this.moveDelta(delta);
	}
	
	private void moveDelta(DeltaState delta) {
		this.move(getXMove(delta), getYMove(delta));
	}

	private double getXMove(DeltaState delta){
		return this.xMove * delta.getDelta();
	}
	
	private double getYMove(DeltaState deltaState){
		return this.yMove * deltaState.getDelta();
	}

	public MovingVertical getMovingStateV() {
		return vMovingState;
	}
	
	public MovingHorizontal getMovingStateH() {
		return hMovingState;
	}

	
	
	
	public MovingState getVMovingState() {
		return vMovingState;
	}
	
	public MovingState getHMovingState() {
		return hMovingState;
	}

	public void setRightEstado() {
		this.hMovingState = MovingToRight.getInstance();		
	}

	public void setLeftEstado() {
		this.hMovingState = MovingToLeft.getInstance();				
	}

	public void setTopEstate() {
		this.vMovingState = MovingToTop.getInstance();
	}
	
	public void setBottomEstate() {
		this.vMovingState = MovingToBottom.getInstance();
	}	

	public void setNoneEstadoH() {
		this.hMovingState = MovingNoneH.getInstance();		
	}
	public void setNoneEstadoV() {
		this.vMovingState = MovingNoneV.getInstance();		
	}

	public void speedUp(DeltaState deltaState) {
		this.xMove += Math.cos(currentAngle) * deltaState.getDelta() * ACCELERATION;
		this.yMove -= Math.sin(currentAngle) * deltaState.getDelta() * ACCELERATION;
		this.tempHip = xMove*xMove + yMove*yMove;
		if(tempHip > TOPSPEEDSQUARE ){
			xMove = xMove*TOPSPEEDSQUARE/tempHip;
			yMove = yMove*TOPSPEEDSQUARE/tempHip;
		}
	}


	public abstract void updateRenderAngle();

	public void turnLeft(DeltaState deltaState) {
		addAngle(deltaState.getDelta() * TURNSPEED);
		updateRenderAngle();
	}

	public void turnRight(DeltaState deltaState) {
		decreaseAngle(deltaState.getDelta() * TURNSPEED);
		updateRenderAngle();
	}

	private void addAngle(double add) {
		if((currentAngle += add) > MAXANGLE){
			currentAngle = currentAngle % MAXANGLE ;
		}
	}

	private void decreaseAngle(double add) {
		if((currentAngle -= add) < 0){
			currentAngle = (currentAngle % MAXANGLE) + MAXANGLE ;
		}
	}

	public double getSpriteAngle() {
		return  - currentAngle + Math.PI / 2;
	}

	public void speedDown(DeltaState deltaState) {
		
	}
}
